#!/usr/bin/env python

import logging
import os

import pika
from util.CustomConfigParser import CustomConfigParser


class AmqBlockingPublisher:
    def __init__(self, configfile='rabbitmq.cfg'):
        """Class for Blocking rabbitmq Publisher to transmit data.

        Args:
            configfile (str) : Filename of config file.

        Returns:
            The return value. True for success, False otherwise.

        """

        parser = CustomConfigParser()
        settings = parser.read_config(configfile)

        # read rabbitmq settings from config file
        self.settings = settings['rabbitmq']
        self.login = pika.PlainCredentials(os.getenv('RABBITMQ_USER', self.settings['user']),
                                           os.getenv('RABBITMQ_PW', self.settings['pw']))
        self.connection_parameter = pika.ConnectionParameters(host=os.getenv('RABBITMQ_IP', self.settings['ip']),
                                                              port=int(os.getenv('RABBITMQ_PORT',
                                                                                 self.settings['data_port'])),
                                                              virtual_host=os.getenv('RABBITMQ_VHOST',
                                                                                     self.settings['vhost']),
                                                              credentials=self.login,
                                                              connection_attempts=int(
                                                                  self.settings['connection_attempts']),
                                                              retry_delay=int(self.settings['retry_delay']),
                                                              heartbeat=0)
        self.connection = None
        self.channel = None

    def connect(self):
        """Open rabbitmq connection."""

        if not self.connection or self.connection.is_closed:
            self.connection = pika.BlockingConnection(self.connection_parameter)
            self.channel = self.connection.channel()
            self.channel.queue_declare(
                queue=os.getenv('RABBITMQ_QUEUE', self.settings['queue'])
            )

    def publish_message(self, msg):
        """Try to publish message. Reconnect if connection is closed

        Throw execption to be caught by pipeline if channel not open."""

        try:
            self.channel.basic_publish(exchange=self.settings['exchange'],
                                       routing_key=self.settings['routing_key'],
                                       body=msg,
                                       properties=pika.BasicProperties(
                                           # make message persistent
                                           delivery_mode=2)
                                       )
        except (pika.exceptions.ConnectionClosed, pika.exceptions.ChannelClosed):

            logging.error('Trying to reconnect')
            try:
                self.connect()
                return self.channel.basic_publish(exchange=self.settings['exchange'],
                                                  routing_key=self.settings['routing_key'],
                                                  body=msg,
                                                  properties=pika.BasicProperties(
                                                      # make message persistent
                                                      delivery_mode=2))
            except (pika.exceptions.ConnectionClosed, pika.exceptions.ChannelClosed):
                logging.error('Reconnect failed')
                raise

    def close(self):
        """Close connection."""

        if self.channel and self.channel.is_open:
            self.channel.close()
        logging.info('Channel closed')
        if self.connection and self.connection.is_open:
            self.connection.close()
        logging.info('Connection closed')


